package top.korori.oss.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.ciModel.job.MediaJobResponse;
import com.qcloud.cos.model.ciModel.job.MediaJobsRequest;
import com.qcloud.cos.model.ciModel.snapshot.SnapshotRequest;
import com.qcloud.cos.model.ciModel.snapshot.SnapshotResponse;
import com.qcloud.cos.region.Region;
import com.tencent.cloud.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.korori.common.exception.BizException;
import top.korori.oss.entity.res.CosTmpKeyVo;
import top.korori.oss.properties.CosConfig;

import java.io.IOException;
import java.io.InputStream;
import java.util.TreeMap;

@Service
@Slf4j
public class CosService {

    @Autowired
    private CosConfig cosConfig;

    public String putObj(InputStream input, String path) {

        COSClient client = createClient();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosConfig.getBucket(), path, input, objectMetadata);
        //putObjectRequest.setStorageClass(StorageClass.Standard);
        try {
            client.putObject(putObjectRequest);
            return path;
        } catch (Exception e) {
            log.error("cos上传文件出错:{}", e.getMessage(), e);
            throw new BizException("cos上传文件出错");
        } finally {
            client.shutdown();

            try {
                input.close();
            } catch (IOException e) {
                log.error("cos上传文件出错:{}", e.getMessage(), e);
            }
        }
    }

    public CosTmpKeyVo uploadFileTmpKey(String path) {

        TreeMap<String, Object> config = new TreeMap<String, Object>();
        try {
            setCosConfig(config);
            Policy policy = new Policy();
            Statement statement = new Statement();
            statement.setEffect("allow");

            statement.addActions(new String[]{
                    "cos:PutObject",
                    "cos:PostObject",
                    "cos:InitiateMultipartUpload",
                    "cos:ListMultipartUploads",
                    "cos:ListParts",
                    "cos:UploadPart",
                    "cos:CompleteMultipartUpload",
                    "ci:CreateMediaJobs",
                    "ci:CreateFileProcessJobs"
            });

            statement.addResources(new String[]{
                    String.format("qcs::cos:%s:uid/%s:%s/%s", cosConfig.getRegion(), cosConfig.getAppId(), cosConfig.getBucket(), path)
            });

            policy.addStatement(statement);

            config.put("policy", JSON.toJSONString(policy));
            Response response = CosStsClient.getCredential(config);
            CosTmpKeyVo tmpKeyRes = createTmpKeyRes(response);
            tmpKeyRes.setKey(path);
            return tmpKeyRes;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BizException("请求临时密钥异常");
        }
    }

    public CosTmpKeyVo putObjTmpKey(String path, Integer maxLength) {

        TreeMap<String, Object> config = new TreeMap<String, Object>();
        try {
            setCosConfig(config);
            Policy policy = new Policy();
            Statement statement = new Statement();
            statement.setEffect("allow");

            statement.addActions(new String[]{
                    "cos:PutObject",
                    "cos:PostObject",
            });

            statement.addResources(new String[]{
                    String.format("qcs::cos:%s:uid/%s:%s/%s", cosConfig.getRegion(), cosConfig.getAppId(), cosConfig.getBucket(), path)
            });

            policy.addStatement(statement);
            JSONObject policyJson = (JSONObject) JSONObject.toJSON(policy);

            JSONArray statementArray = (JSONArray) policyJson.get("statement");
            JSONObject statementObj = (JSONObject) statementArray.get(0);

            JSONObject condition = (JSONObject) JSON.parse("{\n" +
                    "\t\"numeric_greater_than_equal\": {\n" +
                    "\t\t\"cos:content-length\": 1\n" +
                    "\t},\n" +
                    "\t\"numeric_less_than\": {\n" +
                    "\t\t\"cos:content-length\": " + maxLength * 1024 + "\n" +
                    "\t}\n" +
                    "}");
            statementObj.put("condition", condition);

            config.put("policy", JSON.toJSONString(policyJson));
            Response response = CosStsClient.getCredential(config);
            CosTmpKeyVo tmpKeyRes = createTmpKeyRes(response);
            tmpKeyRes.setKey(path);
            return tmpKeyRes;
        } catch (Exception e) {
            log.error("请求临时密钥异常: {}", e.getMessage(), e);
            throw new BizException("请求临时密钥异常");
        }
    }

    public String snapshot(String inputObj, String outputObj, String time) {
        COSClient client = null;
        try {
            client = createClient();
            SnapshotRequest request = new SnapshotRequest();
            request.setBucketName(cosConfig.getBucket());
            request.getInput().setObject(inputObj);
            request.getOutput().setBucket(cosConfig.getBucket());
            request.getOutput().setRegion(cosConfig.getRegion());
            request.getOutput().setObject(outputObj);
            request.setTime(time);
            SnapshotResponse response = client.generateSnapshot(request);
            client.shutdown();
            return response.getOutput().getObject();

        } catch (Exception e) {
            log.error("获取视频封面异常: {}", e.getMessage(), e);
            throw new BizException("获取视频封面异常");
        } finally {
            assert client != null;
            client.shutdown();
        }
    }


    /**
     * 智能封面
     *
     * @param objPath 视频路径
     * @return 封面路径
     */
    public String smartCoverToJpg(String objPath) {

        COSClient client = createClient();

        //1.创建任务请求对象
        MediaJobsRequest request = new MediaJobsRequest();
        //2.添加请求参数 参数详情请见 API 接口文档
        request.setBucketName(cosConfig.getBucket());
        request.setTag("SmartCover");
        request.getInput().setObject(objPath);
        request.getOperation().setTemplateId("t19696426befc64eebb058a9f451957f58");
        request.getOperation().getOutput().setBucket(cosConfig.getBucket());
        request.getOperation().getOutput().setRegion(cosConfig.getRegion());
        request.getOperation().getOutput().setObject("cover/1.jpg");
        //3.调用接口,获取任务响应对象
        MediaJobResponse response = client.createMediaJobs(request);
        System.out.println(response.getJobsDetail().getOperation().getOutput().getObject());
        client.shutdown();
        return null;
    }

    private COSClient createClient() {
        COSCredentials cred = new BasicCOSCredentials(cosConfig.getSecretId(), cosConfig.getSecretKey());
        Region region = new Region(cosConfig.getRegion());
        ClientConfig clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        return new COSClient(cred, clientConfig);
    }

    private void setCosConfig(TreeMap<String, Object> config) {
        config.put("secretId", cosConfig.getSecretId());
        config.put("secretKey", cosConfig.getSecretKey());
        config.put("durationSeconds", cosConfig.getDurationSeconds());
        config.put("bucket", cosConfig.getBucket());
        config.put("region", cosConfig.getRegion());
    }

    private CosTmpKeyVo createTmpKeyRes(Response response) {
        CosTmpKeyVo cosTmpKeyVo = new CosTmpKeyVo();
        cosTmpKeyVo.setTmpSecretId(response.credentials.tmpSecretId);
        cosTmpKeyVo.setTmpSecretKey(response.credentials.tmpSecretKey);
        cosTmpKeyVo.setSessionToken(response.credentials.sessionToken);
        cosTmpKeyVo.setRegion(cosConfig.getRegion());
        cosTmpKeyVo.setBucket(cosConfig.getBucket());
        cosTmpKeyVo.setStartTime(response.startTime);
        cosTmpKeyVo.setExpiredTime(response.expiredTime);
        return cosTmpKeyVo;
    }

}
